using System;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using KenEgozi.Com.Weblog.Application;

namespace KenEgozi.Com.Weblog.Application
{
	public static class Hashing
	{
		readonly static Hashtable hashAlgorithms = Hashtable.Synchronized(new Hashtable());

		/// <summary>
		/// Hashing a given string with SHA2.
		/// </summary>
		/// <param name="data">Data to hash</param>
		/// <returns>Hashed data</returns>
		public static string HashData(string data)
		{
			return HashData(data, HashType.SHA256);
		}

		/// <summary>
		/// Hashing a given string with any of the supported hash algorithms.
		/// </summary>
		/// <param name="data">Data to hash</param>
		/// <param name="hashType">Hashing algorithm to use</param>
		/// <returns>Hashed data</returns>
		public static string HashData(string data, HashType hashType)
		{
			HashAlgorithm hash = GetHash(hashType);
			byte[] bytes = (new UnicodeEncoding()).GetBytes(data);
			byte[] hashed = hash.ComputeHash(bytes);
			StringBuilder sb = new StringBuilder(64);
			foreach (byte b in hashed)
				sb.AppendFormat("{0:x2}", b);
			return sb.ToString();
		}

		private static HashAlgorithm GetHash(HashType hashType)
		{
			if (!hashAlgorithms.ContainsKey(hashType))
				hashAlgorithms.Add(hashType, CreateaHashAlgorithm(hashType));
			return hashAlgorithms[hashType] as HashAlgorithm;
		}

		private static HashAlgorithm CreateaHashAlgorithm(HashType hashType)
		{
			switch (hashType)
			{
				case HashType.MD5:
					return new MD5CryptoServiceProvider();
				case HashType.SHA1:
					return new SHA1Managed();
				case HashType.SHA256:
					return new SHA256Managed();
				case HashType.SHA384:
					return new SHA384Managed();
				case HashType.SHA512:
					return new SHA512Managed();
				default:
					throw new NotImplementedException();
			}
		}

	}

	public enum HashType
	{
		MD5,
		SHA1,
		SHA256,
		SHA384,
		SHA512
	}

}
